package com.thiswhyme.common.utils.codec;

import com.thiswhyme.common.expection.BusinessException;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * @description: AES工具
 * @date: 2021/9/13
 */
@Slf4j
public class AesUtils {

    /**
     * 可配置到Constant中，并读取配置文件注入,16位,自己定义
     */
    private static final String KEY = "qazwsx9876$%@okm";

    /**
     * 参数分别代表 算法名称/加密模式/数据填充方式
     */
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

    /**
     * 随机生成密钥
     * @return
     */
    public static String createSecretKey() throws Exception {
        // KeyGenerator提供对称密钥生成器的功能，支持各种算法
        KeyGenerator keygen = KeyGenerator.getInstance(EncryptAlgorithm.AES.name());
        keygen.init(128);

        // SecretKey负责保存对称密钥
        SecretKey deskey = keygen.generateKey();
        byte[] key = deskey.getEncoded();
        return CodecUtils.bytes2Base64String(key);
    }

    /**
     * 加密
     * @param content 加密的字符串（String）
     * @param encryptKey key值（String）
     * @return 返回加密后的结果（base64String）
     */
    public static String encrypt(String content, String encryptKey) {
        return encrypt(content, encryptKey.getBytes());
    }

    /**
     * 加密
     * @param content 加密的字符串（String）
     * @param encryptKey key值（String）
     * @return 返回加密后的结果（base64String）
     */
    public static String encrypt(String content, byte[] encryptKey) {
        String result = null;
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey, EncryptAlgorithm.AES.name()));
            byte[] b = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            // 采用base64算法进行转码,避免出现中文乱码
            result = CodecUtils.bytes2Base64String(b);
        } catch (Exception ex) {
            log.error("AES加密异常", ex);
            throw new BusinessException("AES加密异常");
        }
        return result;
    }

    /**
     * 解密
     * @param encryptStr 解密的字符串（base64String）
     * @param decryptKey 解密的key值（String）
     * @return 返回解密后的结果（String）
     */
    public static String decrypt(String encryptStr, String decryptKey) {
        return decrypt(encryptStr, decryptKey.getBytes());
    }

    /**
     * 解密
     * @param encryptStr 解密的字符串（base64String）
     * @param decryptKey 解密的key值
     * @return 返回解密后的结果（String）
     */
    public static String decrypt(String encryptStr, byte[] decryptKey) {
        String result = null;
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey, EncryptAlgorithm.AES.name()));
            // 采用base64算法进行转码,避免出现中文乱码
            byte[] encryptBytes = CodecUtils.base64String2Bytes(encryptStr);
            byte[] decryptBytes = cipher.doFinal(encryptBytes);
            result = new String(decryptBytes);
        } catch (Exception ex) {
            log.error("AES解密异常", ex);
            throw new BusinessException("AES解密异常");
        }
        return result;
    }

    /**
     * AES加密
     * @param content 原文内容（String）
     * @return 加密字符（base64String）
     */
    public static String encrypt(String content) {
        return encrypt(content, KEY);
    }

    /**
     * AES解密
     * @param encryptStr 密文（base64String）
     * @return 返回原文内容（String）
     * @throws Exception 异常
     */
    public static String decrypt(String encryptStr) {
        return decrypt(encryptStr, KEY);
    }
}
